package com.example.program

import kotlinx.coroutines.*
import org.junit.Test


/**
 * 三个协程任务，要求都执行完成以后进行处理
 *
 * @author zhouronghua
 * @time 2022/3/25 8:53 上午
 */
class ThreeJobTest {

    /**
     * 测试三个协程任务，要求全部完成后再处理其他
     * 第一种情况：三个任务并发执行
     *
     */
    @Test
    fun testThreeJob() = runBlocking {
        val scope = CoroutineScope(Dispatchers.Default)
        val deferred1 = scope.async {
            try {
                println("job 1 started")
                delay(3000)
                println("job 1 finished ${Thread.currentThread().id} ")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        val deferred2 = scope.async {
            try {
                println("job 2 started")
                delay(2000)
                println("job 2 finished ${Thread.currentThread().id}")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        val deferred3 = scope.async {
            try {
                println("job3 started ")
                delay(5000)
                println("job 3 finished ${Thread.currentThread().id}")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
//        deferred1.await()
//        deferred2.await()
//        deferred3.await()
        // 等待全部任务执行
        awaitAll(deferred1, deferred2, deferred3)
        println("三个任务执行完成")
    }

    /**
     * 测试三个任务按顺序执行
     * 思路：采用Flow方式处理
     */
    @Test
    fun testThreeJobFlow() = runBlocking {
        val scope = CoroutineScope(Dispatchers.Default)
        val deferred1 = scope.async {
            startJob1()
            startJob2()
            startJob3()
        }
        deferred1.await()
        println("协程任务执行完成")
    }

    /**
     * 测试三个任务，任务1--》任务2--》任务三
     * 能够保证完成但不能保证有序
     */
    @InternalCoroutinesApi
    @Test
    fun testThreeJobJoin() = runBlocking {
        val scope = CoroutineScope(Dispatchers.Default)
        val job1 = scope.launch {
            try {
                println("job 1 started")
                delay(3000)
                println("job 1 finished ${Thread.currentThread().id} ")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        val job2 = scope.launch {
            try {
                println("job 2 started")
                delay(2000)
                println("job 2 finished ${Thread.currentThread().id}")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        val job3 = scope.launch {
            try {
                println("job3 started ")
                delay(5000)
                println("job 3 finished ${Thread.currentThread().id}")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        job1.invokeOnCompletion {

        }
        job2.invokeOnCompletion {

        }
        job3.invokeOnCompletion {

        }
        joinAll(job1, job2, job3)
        println("协程任务执行完成")
    }

    private suspend fun startJob3() {
        try {
            println("job3 started ")
            delay(5000)
            println("job 3 finished ${Thread.currentThread().id}")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private suspend fun startJob2() {
        try {
            println("job 2 started")
            delay(2000)
            println("job 2 finished ${Thread.currentThread().id}")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private suspend fun startJob1() {
        try {
            println("job 1 started")
            delay(3000)
            println("job 1 finished ${Thread.currentThread().id} ")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}